home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb.new / gdb-3.98 / gdb / i386-xdep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-01  |  9.3 KB  |  358 lines

  1. /* Intel 386 stuff.
  2.    Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include "defs.h"
  22. #include "param.h"
  23. #include "frame.h"
  24. #include "inferior.h"
  25. #include "gdbcore.h"
  26.  
  27. #ifdef USG
  28. #include <sys/types.h>
  29. #endif
  30.  
  31. #include <sys/param.h>
  32. #include <sys/dir.h>
  33. #include <signal.h>
  34. #include <sys/user.h>
  35. #include <sys/ioctl.h>
  36. #include <fcntl.h>
  37.  
  38. #include <sys/file.h>
  39. #include <sys/stat.h>
  40.  
  41. #include <sys/reg.h>
  42.  
  43. /* this table must line up with REGISTER_NAMES in m-i386.h */
  44. /* symbols like 'EAX' come from <sys/reg.h> */
  45. static int regmap[] = 
  46. {
  47.   EAX, ECX, EDX, EBX,
  48.   UESP, EBP, ESI, EDI,
  49.   EIP, EFL, CS, SS,
  50.   DS, ES, FS, GS,
  51. };
  52.  
  53. /* blockend is the value of u.u_ar0, and points to the
  54.  * place where GS is stored
  55.  */
  56. i386_register_u_addr (blockend, regnum)
  57. {
  58. #if 0
  59.   /* this will be needed if fp registers are reinstated */
  60.   /* for now, you can look at them with 'info float'
  61.    * sys5 wont let you change them with ptrace anyway
  62.    */
  63.   if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM) 
  64.     {
  65.       int ubase, fpstate;
  66.       struct user u;
  67.       ubase = blockend + 4 * (SS + 1) - KSTKSZ;
  68.       fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
  69.       return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
  70.     } 
  71.   else
  72. #endif
  73.     return (blockend + 4 * regmap[regnum]);
  74.   
  75. }
  76.  
  77. /* This is broken for cross debugging.  Possible solutions are:
  78.  
  79. 1.  Don't worry about whether the thing compiles for cross-debugging.
  80. Go ahead and call them from i386-tdep.c.
  81. 1a.  Same thing but use some macros in xm-i386.h so that gdb will
  82. compile for cross-debugging but just give an error (or some such behavior)
  83. when you attempt to convert floats.
  84.  
  85. 2.  Write a portable (in the sense of running on any machine; it would
  86. always be for i387 floating-point formats) extended<->double converter
  87. (which just deals with the values as arrays of char).
  88.  
  89. 3.  Assume the host machine has *some* IEEE chip.  However, IEEE does
  90. not standardize formats for extended floats (387 is 10 bytes, 68881 is
  91. 12 bytes), so this won't work.  */
  92.  
  93. i387_to_double (from, to)
  94.      char *from;
  95.      char *to;
  96. {
  97.   long *lp;
  98.   /* push extended mode on 387 stack, then pop in double mode
  99.    *
  100.    * first, set exception masks so no error is generated -
  101.    * number will be rounded to inf or 0, if necessary 
  102.    */
  103.   asm ("pushl %eax");         /* grab a stack slot */
  104.   asm ("fstcw (%esp)");        /* get 387 control word */
  105.   asm ("movl (%esp),%eax");    /* save old value */
  106.   asm ("orl $0x3f,%eax");        /* mask all exceptions */
  107.   asm ("pushl %eax");
  108.   asm ("fldcw (%esp)");        /* load new value into 387 */
  109.   
  110.   asm ("movl 8(%ebp),%eax");
  111.   asm ("fldt (%eax)");        /* push extended number on 387 stack */
  112.   asm ("fwait");
  113.   asm ("movl 12(%ebp),%eax");
  114.   asm ("fstpl (%eax)");        /* pop double */
  115.   asm ("fwait");
  116.   
  117.   asm ("popl %eax");        /* flush modified control word */
  118.   asm ("fnclex");            /* clear exceptions */
  119.   asm ("fldcw (%esp)");        /* restore original control word */
  120.   asm ("popl %eax");        /* flush saved copy */
  121. }
  122.  
  123. double_to_i387 (from, to)
  124.      char *from;
  125.      char *to;
  126. {
  127.   /* push double mode on 387 stack, then pop in extended mode
  128.    * no errors are possible because every 64-bit pattern
  129.    * can be converted to an extended
  130.    */
  131.   asm ("movl 8(%ebp),%eax");
  132.   asm ("fldl (%eax)");
  133.   asm ("fwait");
  134.   asm ("movl 12(%ebp),%eax");
  135.   asm ("fstpt (%eax)");
  136.   asm ("fwait");
  137. }
  138.  
  139. struct env387 
  140. {
  141.   unsigned short control;
  142.   unsigned short r0;
  143.   unsigned short status;
  144.   unsigned short r1;
  145.   unsigned short tag;
  146.   unsigned short r2;
  147.   unsigned long eip;
  148.   unsigned short code_seg;
  149.   unsigned short opcode;
  150.   unsigned long operand;
  151.   unsigned short operand_seg;
  152.   unsigned short r3;
  153.   unsigned char regs[8][10];
  154. };
  155.  
  156. static
  157. print_387_control_word (control)
  158. unsigned short control;
  159. {
  160.   printf ("control 0x%04x: ", control);
  161.   printf ("compute to ");
  162.   switch ((control >> 8) & 3) 
  163.     {
  164.     case 0: printf ("24 bits; "); break;
  165.     case 1: printf ("(bad); "); break;
  166.     case 2: printf ("53 bits; "); break;
  167.     case 3: printf ("64 bits; "); break;
  168.     }
  169.   printf ("round ");
  170.   switch ((control >> 10) & 3) 
  171.     {
  172.     case 0: printf ("NEAREST; "); break;
  173.     case 1: printf ("DOWN; "); break;
  174.     case 2: printf ("UP; "); break;
  175.     case 3: printf ("CHOP; "); break;
  176.     }
  177.   if (control & 0x3f) 
  178.     {
  179.       printf ("mask:");
  180.       if (control & 0x0001) printf (" INVALID");
  181.       if (control & 0x0002) printf (" DENORM");
  182.       if (control & 0x0004) printf (" DIVZ");
  183.       if (control & 0x0008) printf (" OVERF");
  184.       if (control & 0x0010) printf (" UNDERF");
  185.       if (control & 0x0020) printf (" LOS");
  186.       printf (";");
  187.     }
  188.   printf ("\n");
  189.   if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
  190.                 control & 0xe080);
  191. }
  192.  
  193. static
  194. print_387_status_word (status)
  195.      unsigned short status;
  196. {
  197.   printf ("status 0x%04x: ", status);
  198.   if (status & 0xff) 
  199.     {
  200.       printf ("exceptions:");
  201.       if (status & 0x0001) printf (" INVALID");
  202.       if (status & 0x0002) printf (" DENORM");
  203.       if (status & 0x0004) printf (" DIVZ");
  204.       if (status & 0x0008) printf (" OVERF");
  205.       if (status & 0x0010) printf (" UNDERF");
  206.       if (status & 0x0020) printf (" LOS");
  207.       if (status & 0x0040) printf (" FPSTACK");
  208.       printf ("; ");
  209.     }
  210.   printf ("flags: %d%d%d%d; ",
  211.       (status & 0x4000) != 0,
  212.       (status & 0x0400) != 0,
  213.       (status & 0x0200) != 0,
  214.       (status & 0x0100) != 0);
  215.   
  216.   printf ("top %d\n", (status >> 11) & 7);
  217. }
  218.  
  219. static
  220. print_387_status (status, ep)
  221.      unsigned short status;
  222.      struct env387 *ep;
  223. {
  224.   int i;
  225.   int bothstatus;
  226.   int top;
  227.   int fpreg;
  228.   unsigned char *p;
  229.   
  230.   bothstatus = ((status != 0) && (ep->status != 0));
  231.   if (status != 0) 
  232.     {
  233.       if (bothstatus)
  234.     printf ("u: ");
  235.       print_387_status_word (status);
  236.     }
  237.   
  238.   if (ep->status != 0) 
  239.     {
  240.       if (bothstatus)
  241.     printf ("e: ");
  242.       print_387_status_word (ep->status);
  243.     }
  244.   
  245.   print_387_control_word (ep->control);
  246.   printf ("last exception: ");
  247.   printf ("opcode 0x%x; ", ep->opcode);
  248.   printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
  249.   printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
  250.   
  251.   top = (ep->status >> 11) & 7;
  252.   
  253.   printf ("regno  tag  msb              lsb  value\n");
  254.   for (fpreg = 7; fpreg >= 0; fpreg--) 
  255.     {
  256.       double val;
  257.       
  258.       printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
  259.       
  260.       switch ((ep->tag >> (fpreg * 2)) & 3) 
  261.     {
  262.     case 0: printf ("valid "); break;
  263.     case 1: printf ("zero  "); break;
  264.     case 2: printf ("trap  "); break;
  265.     case 3: printf ("empty "); break;
  266.     }
  267.       for (i = 9; i >= 0; i--)
  268.     printf ("%02x", ep->regs[fpreg][i]);
  269.       
  270.       i387_to_double (ep->regs[fpreg], (char *)&val);
  271.       printf ("  %g\n", val);
  272.     }
  273.   if (ep->r0)
  274.     printf ("warning: reserved0 is 0x%x\n", ep->r0);
  275.   if (ep->r1)
  276.     printf ("warning: reserved1 is 0x%x\n", ep->r1);
  277.   if (ep->r2)
  278.     printf ("warning: reserved2 is 0x%x\n", ep->r2);
  279.   if (ep->r3)
  280.     printf ("warning: reserved3 is 0x%x\n", ep->r3);
  281. }
  282.  
  283. #ifndef U_FPSTATE
  284. #define U_FPSTATE(u) u.u_fpstate
  285. #endif
  286.  
  287. i386_float_info ()
  288. {
  289.   struct user u; /* just for address computations */
  290.   int i;
  291.   /* fpstate defined in <sys/user.h> */
  292.   struct fpstate *fpstatep;
  293.   char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
  294.   unsigned int uaddr;
  295.   char fpvalid;
  296.   unsigned int rounded_addr;
  297.   unsigned int rounded_size;
  298.   extern int corechan;
  299.   int skip;
  300.   
  301.   uaddr = (char *)&u.u_fpvalid - (char *)&u;
  302.   if (have_inferior_p()) 
  303.     {
  304.       unsigned int data;
  305.       unsigned int mask;
  306.       
  307.       rounded_addr = uaddr & -sizeof (int);
  308.       data = ptrace (3, inferior_pid, rounded_addr, 0);
  309.       mask = 0xff << ((uaddr - rounded_addr) * 8);
  310.       
  311.       fpvalid = ((data & mask) != 0);
  312.     } 
  313.   else 
  314.     {
  315.       if (lseek (corechan, uaddr, 0) < 0)
  316.     perror ("seek on core file");
  317.       if (myread (corechan, &fpvalid, 1) < 0) 
  318.     perror ("read on core file");
  319.       
  320.     }
  321.   
  322.   if (fpvalid == 0) 
  323.     {
  324.       printf ("no floating point status saved\n");
  325.       return;
  326.     }
  327.   
  328.   uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
  329.   if (have_inferior_p ()) 
  330.     {
  331.       int *ip;
  332.       
  333.       rounded_addr = uaddr & -sizeof (int);
  334.       rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
  335.               sizeof (int) - 1) / sizeof (int);
  336.       skip = uaddr - rounded_addr;
  337.       
  338.       ip = (int *)buf;
  339.       for (i = 0; i < rounded_size; i++) 
  340.     {
  341.       *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
  342.       rounded_addr += sizeof (int);
  343.     }
  344.     } 
  345.   else 
  346.     {
  347.       if (lseek (corechan, uaddr, 0) < 0)
  348.     perror_with_name ("seek on core file");
  349.       if (myread (corechan, buf, sizeof (struct fpstate)) < 0) 
  350.     perror_with_name ("read from core file");
  351.       skip = 0;
  352.     }
  353.   
  354.   fpstatep = (struct fpstate *)(buf + skip);
  355.   print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
  356. }
  357.  
  358.